<?php
/***
 * ActionLeaf (www.actionleaf.com / actionleaf.googlecode.com) PHP Framework
 * Copyright (c) 2008, Wess D. Cope <wess@wattz.net>
 * All rights reserved.								
 * 													
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:                   
 * 																				
 * 	* Redistributions of source code must retain the above copyright notice,	
 * 	this list of conditions and the following disclaimer.						
 * 																				
 * 	* Redistributions in binary form must reproduce the above copyright notice, 
 * 	this list of conditions and the following disclaimer in the documentation   
 * 	and/or other materials provided with the distribution. 						
 * 																				
 * 	* Neither the name of the <ORGANIZATION> nor the names of its contributors may
 * 	be used to endorse or promote products derived from this software without     
 * 	specific prior written permission.											
 * 																				
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 	 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 	 
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 		 
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 	 
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 	 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 	 
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 	 
 * DAMAGE.																				 
 **/

class ALResultObject extends ALData
{

	private $table;
	private $fieldVals = array();  // Associate array that 
	private $primaryKey = null;
	private $primaryKeyVal = 0;
	private $relationResultsName = null;
	private $relationResults = array();
	private $relationType = 0; // 1 = oneToOne, 2 = oneToMany

	/**
	 * Pull database connection and build fields from table column description.  If fieldVals is
	 * passed then the fields and fieldAssoc properties are set  
	 *
	 * @param	string
	 * @param	string
	 * @param	array
	 * @param	string		This is the field name of the primary key
	 * @param	string
	 * @param	int
	 **/
	public function __construct($connectionName, $table, $fieldVals=NO, $primaryKey=NO, $relationResultsName=null, $relationType=0)
	{

		if(!$connectionName||!$table)
			die("No Connection name and/or table name given...");


		parent::__construct($connectionName);

		$this->table = $table;
		$this->relationResultsName = $relationResultsName;
		$this->relationType = $relationType;

		// Build fields/fieldAssoc
		if (empty($fieldVals)&&empty($primaryKey)) {
			$this->describeTable();
		} else {
			$this->fieldVals = $fieldVals;
			if (isset($this->fieldVals[$primaryKey])) {
				$this->primaryKey = $primaryKey;
				$this->primaryKeyVal = $this->fieldVals[$primaryKey];
			} else {
				die('ALResultObject::__construct Error: fieldVals does not contain a field key that matches the passed primaryKey');
			}
		}

	}

	/**
	 * Return a single column value.
	 *
	 * @param	string		This is the 
	 **/
	public function __get($var)
	{

		// Return relation results
		if ($this->relationType && $var == $this->relationResultsName && count($this->relationResults)) {
			if (count($this->relationResults)) {
				return $this->getRelationResults();
			} else {
				return ($this->relationType==1)?'':array();
			}
		}

		return isset($this->fieldVals[$var])?$this->fieldVals[$var]:false;

	}

	/**
	 * Set a single field value.
	 *
	 * @param	string
	 * @param	string
	 **/
	public function __set($var, $val)
	{

		if($var == $this->primaryKey) {

			die("You cannot set the value of a primary key {$var}, {$val}");

		} else {

			$this->fieldVals[$var] = $val;

		}

	}
	
	/**
	 * Return single object if only a single relationObject exist.  Return an array if multiple.
	 *
	 * @param	mixed
	 **/
	private function getRelationResults()
	{

		if ($this->relationType == 2 && count($this->relationResults)) {
			return $this->relationResults;
		} else if ($this->relationType == 1 && isset($this->relationResults[0])) {
			return $this->relationResults[0];
		}

		return false;

	}

	/**
	 * Builds internal table fields array and primary key using a sql DESCRIBE query.
	 *
	 * @return	null
	 **/
	private function describeTable()
	{

		$res = $this->currentConnection->query("DESCRIBE " . $this->table);
		if($res) {

			$resultSet = $res->fetchAll(PDO::FETCH_OBJ);
			foreach($resultSet as $f) {
				if($f->Key == "PRI")
					$this->primaryKey = $f->Field;
				$this->fieldVals[$f->Field] = null;
			}

		}

	}

	/**
	 * Add relationship result object
	 *
	 * @param	object
	 *
	 * @return	null
	 **/
	public function addRelationItem($resultObject)
	{

		$this->relationResults[] = $resultObject;

	}

	/**
	 * Save this item to the database.  Checks if the primary key value is set(>0) and does an INSERT or
	 * UPDATE accordingly.
	 *
	 * @return		bool
	 **/
	public function save()
	{

		if ($this->primaryKeyVal) { 

			// Update Row
			$colItems=array();
			$colBinds=array();
			foreach($this->fieldVals AS $colName=>$value) {
				if ($colName!=$this->primaryKey&&isset($value)) {
					$colItems[] = "{$colName} = :{$colName}";
					$colBinds[":{$colName}"]=$value;
				}
			}
			$sql = "UPDATE {$this->table} SET ".implode(', ', $colItems)." WHERE {$this->primaryKey} = {$this->primaryKeyVal}";
			$stmt = $this->currentConnection->prepare($sql);
			if ($stmt->execute($colBinds)) {

				$this->errorDetails = null;
				return true;

			} else {

				$this->errorDetails = $stmt->errorInfo();
				return false;

			}

		} else {

			// Insert New Row
			$colNames=array();
			$colBindNames=array();
			$colBinds=array();
			foreach($this->fieldVals AS $colName=>$value) {
				if ($colName!=$this->primaryKey&&isset($value)) {
					$colNames[] = $colName;
					$colBindNames[] = ":$colName";
					$colBinds[":{$colName}"]=$value;
				}
			}
			$sql = "INSERT INTO {$this->table} (`".implode('`, `', $colNames)."`) VALUES (".implode(', ', $colBindNames).")";
			$stmt = $this->currentConnection->prepare($sql);
			if ($stmt->execute($colBinds)) {

				$this->errorDetails = null;
				$this->primaryKeyVal = $this->currentConnection->lastInsertId();
				$this->fieldVals[$this->primaryKey] = $this->primaryKeyVal;
				return true;

			} else {

				$this->errorDetails = $stmt->errorInfo();
				return false;

			}

		}

	}
	
	/**
	 * Delete item from the database
	 * 
	 * @return	bool
	 **/
	public function delete()
	{

		if ($this->primaryKeyVal) { 

			$sql = "DELETE FROM {$this->table} WHERE {$this->primaryKey} = {$this->primaryKeyVal}";
			return (bool)$this->currentConnection->exec($sql);

		} else {

			return false;

		}

	}

}
